home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / dflt14.zip / POPDOWN.C < prev    next >
Text File  |  1992-05-14  |  12KB  |  370 lines

  1. /* ------------- popdown.c ----------- */
  2.  
  3. #include "dflat.h"
  4.  
  5. static int SelectionWidth(struct PopDown *);
  6. static int py = -1;
  7.  
  8. /* ------------ CREATE_WINDOW Message ------------- */
  9. static int CreateWindowMsg(WINDOW wnd)
  10. {
  11.     int rtn;
  12.     ClearAttribute(wnd, HASTITLEBAR     |
  13.                         VSCROLLBAR     |
  14.                         MOVEABLE     |
  15.                         SIZEABLE     |
  16.                         HSCROLLBAR);
  17.     rtn = BaseWndProc(POPDOWNMENU, wnd, CREATE_WINDOW, 0, 0);
  18.     SendMessage(wnd, CAPTURE_MOUSE, 0, 0);
  19.     SendMessage(wnd, CAPTURE_KEYBOARD, 0, 0);
  20.     SendMessage(NULL, SAVE_CURSOR, 0, 0);
  21.     SendMessage(NULL, HIDE_CURSOR, 0, 0);
  22.     wnd->oldFocus = inFocus;
  23.     inFocus = wnd;
  24.     return rtn;
  25. }
  26.  
  27. /* --------- LEFT_BUTTON Message --------- */
  28. static void LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  29. {
  30.     int my = (int) p2 - GetTop(wnd);
  31.     if (InsideRect(p1, p2, ClientRect(wnd)))    {
  32.         if (my != py)    {
  33.             SendMessage(wnd, LB_SELECTION,
  34.                     (PARAM) wnd->wtop+my-1, TRUE);
  35.             py = my;
  36.         }
  37.     }
  38.     else if ((int)p2 == GetTop(GetParent(wnd)))
  39.         if (GetClass(GetParent(wnd)) == MENUBAR)
  40.             PostMessage(GetParent(wnd), LEFT_BUTTON, p1, p2);
  41. }
  42.  
  43. /* -------- BUTTON_RELEASED Message -------- */
  44. static BOOL ButtonReleasedMsg(WINDOW wnd, PARAM p1, PARAM p2)
  45. {
  46.     py = -1;
  47.     if (InsideRect((int)p1, (int)p2, ClientRect(wnd)))    {
  48.         int sel = (int)p2 - GetClientTop(wnd);
  49.         if (*TextLine(wnd, sel) != LINE)
  50.             SendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
  51.     }
  52.     else    {
  53.         WINDOW pwnd = GetParent(wnd);
  54.         if (GetClass(pwnd) == MENUBAR && (int)p2==GetTop(pwnd))
  55.             return FALSE;
  56.         if ((int)p1 == GetLeft(pwnd)+2)
  57.             return FALSE;
  58.         SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  59.         return TRUE;
  60.     }
  61.     return FALSE;
  62. }
  63.  
  64. /* --------- PAINT Message -------- */
  65. static void PaintMsg(WINDOW wnd)
  66. {
  67.     int wd;
  68.     unsigned char sep[80], *cp = sep;
  69.     unsigned char sel[80];
  70.     struct PopDown *ActivePopDown;
  71.     struct PopDown *pd1;
  72.  
  73.     ActivePopDown = pd1 = wnd->mnu->Selections;
  74.     wd = MenuWidth(ActivePopDown)-2;
  75.     while (wd--)
  76.         *cp++ = LINE;
  77.     *cp = '\0';
  78.     SendMessage(wnd, CLEARTEXT, 0, 0);
  79.     wnd->selection = wnd->mnu->Selection;
  80.     while (pd1->SelectionTitle != NULL)    {
  81.         if (*pd1->SelectionTitle == LINE)
  82.             SendMessage(wnd, ADDTEXT, (PARAM) sep, 0);
  83.         else    {
  84.             int len;
  85.             memset(sel, '\0', sizeof sel);
  86.             if (pd1->Attrib & INACTIVE)
  87.                 /* ------ inactive menu selection ----- */
  88.                 sprintf(sel, "%c%c%c",
  89.                     CHANGECOLOR,
  90.                     wnd->WindowColors [HILITE_COLOR] [FG]|0x80,
  91.                     wnd->WindowColors [STD_COLOR] [BG]|0x80);
  92.             strcat(sel, " ");
  93.             if (pd1->Attrib & CHECKED)
  94.                 /* ---- paint the toggle checkmark ---- */
  95.                 sel[strlen(sel)-1] = CHECKMARK;
  96.             len=CopyCommand(sel+strlen(sel),pd1->SelectionTitle,
  97.                     pd1->Attrib & INACTIVE,
  98.                     wnd->WindowColors [STD_COLOR] [BG]);
  99.             if (pd1->Accelerator)    {
  100.                 /* ---- paint accelerator key ---- */
  101.                 int i;
  102.                 int wd1 = 2+SelectionWidth(ActivePopDown) -
  103.                                     strlen(pd1->SelectionTitle);
  104.                 for (i = 0; keys[i].keylabel; i++)    {
  105.                     if (keys[i].keycode == pd1->Accelerator)   {
  106.                         while (wd1--)
  107.                             strcat(sel, " ");
  108.                         sprintf(sel+strlen(sel), "[%s]",
  109.                             keys[i].keylabel);
  110.                         break;
  111.                     }
  112.                 }
  113.             }
  114.             if (pd1->Attrib & CASCADED)    {
  115.                 /* ---- paint cascaded menu token ---- */
  116.                 if (!pd1->Accelerator)    {
  117.                     wd = MenuWidth(ActivePopDown)-len+1;
  118.                     while (wd--)
  119.                         strcat(sel, " ");
  120.                 }
  121.                 sel[strlen(sel)-1] = CASCADEPOINTER;
  122.             }
  123.             else
  124.                 strcat(sel, " ");
  125.             strcat(sel, " ");
  126.             sel[strlen(sel)-1] = RESETCOLOR;
  127.             SendMessage(wnd, ADDTEXT, (PARAM) sel, 0);
  128.         }
  129.         pd1++;
  130.     }
  131. }
  132.  
  133. /* ---------- BORDER Message ----------- */
  134. static int BorderMsg(WINDOW wnd)
  135. {
  136.     int i, rtn = TRUE;
  137.     WINDOW currFocus;
  138.     if (wnd->mnu != NULL)    {
  139.         currFocus = inFocus;
  140.         inFocus = NULL;
  141.         rtn = BaseWndProc(POPDOWNMENU, wnd, BORDER, 0, 0);
  142.         inFocus = currFocus;
  143.         for (i = 0; i < ClientHeight(wnd); i++)    {
  144.             if (*TextLine(wnd, i) == LINE)    {
  145.                 wputch(wnd, LEDGE, 0, i+1);
  146.                 wputch(wnd, REDGE, WindowWidth(wnd)-1, i+1);
  147.             }
  148.         }
  149.     }
  150.     return rtn;
  151. }
  152.  
  153. /* -------------- LB_CHOOSE Message -------------- */
  154. static void LBChooseMsg(WINDOW wnd, PARAM p1)
  155. {
  156.     struct PopDown *ActivePopDown = wnd->mnu->Selections;
  157.     if (ActivePopDown != NULL)    {
  158.         int *attr = &(ActivePopDown+(int)p1)->Attrib;
  159.         wnd->mnu->Selection = (int)p1;
  160.         if (!(*attr & INACTIVE))    {
  161.             if (*attr & TOGGLE)
  162.                 *attr ^= CHECKED;
  163.             PostMessage(GetParent(wnd), COMMAND,
  164.                 (ActivePopDown+(int)p1)->ActionId, p1);
  165.         }
  166.         else
  167.             beep();
  168.     }
  169. }
  170.  
  171. /* ---------- KEYBOARD Message --------- */
  172. static BOOL KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  173. {
  174.     struct PopDown *ActivePopDown = wnd->mnu->Selections;
  175.     if (wnd->mnu != NULL)    {
  176.         if (ActivePopDown != NULL)    {
  177.             int c = (int)p1;
  178.             int sel = 0;
  179.             int a;
  180.             struct PopDown *pd = ActivePopDown;
  181.  
  182.             if ((c & OFFSET) == 0)
  183.                 c = tolower(c);
  184.             a = AltConvert(c);
  185.  
  186.             while (pd->SelectionTitle != NULL)    {
  187.                 char *cp = strchr(pd->SelectionTitle,
  188.                                 SHORTCUTCHAR);
  189.                 int sc = tolower(*(cp+1));
  190.                 if ((cp && sc == c) ||
  191.                         (a && sc == a) ||
  192.                             pd->Accelerator == c)    {
  193.                     PostMessage(wnd, LB_SELECTION, sel, 0);
  194.                     PostMessage(wnd, LB_CHOOSE, sel, TRUE);
  195.                     return TRUE;
  196.                 }
  197.                 pd++, sel++;
  198.             }
  199.         }
  200.     }
  201.     switch ((int)p1)    {
  202.         case F1:
  203.             if (ActivePopDown == NULL)
  204.                 SendMessage(GetParent(wnd), KEYBOARD, p1, p2);
  205.             else 
  206.                 DisplayHelp(wnd,
  207.                     (ActivePopDown+wnd->selection)->help);
  208.             return TRUE;
  209.         case ESC:
  210.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  211.             return TRUE;
  212.         case FWD:
  213.         case BS:
  214.             if (GetClass(GetParent(wnd)) == MENUBAR)
  215.                 PostMessage(GetParent(wnd), KEYBOARD, p1, p2);
  216.             return TRUE;
  217.         case UP:
  218.             if (wnd->selection == 0)    {
  219.                 if (wnd->wlines == ClientHeight(wnd))    {
  220.                     PostMessage(wnd, LB_SELECTION,
  221.                                     wnd->wlines-1, FALSE);
  222.                     return TRUE;
  223.                 }
  224.             }
  225.             break;
  226.         case DN:
  227.             if (wnd->selection == wnd->wlines-1)    {
  228.                 if (wnd->wlines == ClientHeight(wnd))    {
  229.                     PostMessage(wnd, LB_SELECTION, 0, FALSE);
  230.                     return TRUE;
  231.                 }
  232.             }
  233.             break;
  234.         case HOME:
  235.         case END:
  236.         case '\r':
  237.             break;
  238.         default:
  239.             return TRUE;
  240.     }
  241.     return FALSE;
  242. }
  243.  
  244. /* ----------- CLOSE_WINDOW Message ---------- */
  245. static int CloseWindowMsg(WINDOW wnd)
  246. {
  247.     int rtn;
  248.     WINDOW pwnd = GetParent(wnd);
  249.     SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  250.     SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  251.     SendMessage(NULL, RESTORE_CURSOR, 0, 0);
  252.     inFocus = wnd->oldFocus;
  253.     rtn = BaseWndProc(POPDOWNMENU, wnd, CLOSE_WINDOW, 0, 0);
  254.     SendMessage(pwnd, CLOSE_POPDOWN, 0, 0);
  255.     return rtn;
  256. }
  257.  
  258. /* - Window processing module for POPDOWNMENU window class - */
  259. int PopDownProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  260. {
  261.     switch (msg)    {
  262.         case CREATE_WINDOW:
  263.             return CreateWindowMsg(wnd);
  264.         case LEFT_BUTTON:
  265.             LeftButtonMsg(wnd, p1, p2);
  266.             return FALSE;
  267.         case DOUBLE_CLICK:
  268.             return TRUE;
  269.         case LB_SELECTION:
  270.             if (*TextLine(wnd, (int)p1) == LINE)
  271.                 return TRUE;
  272.             wnd->mnu->Selection = (int)p1;
  273.             break;
  274.         case BUTTON_RELEASED:
  275.             if (ButtonReleasedMsg(wnd, p1, p2))
  276.                 return TRUE;
  277.             break;
  278.         case BUILD_SELECTIONS:
  279.             wnd->mnu = (void *) p1;
  280.             wnd->selection = wnd->mnu->Selection;
  281.             break;
  282.         case PAINT:
  283.             if (wnd->mnu == NULL)
  284.                 return TRUE;
  285.             PaintMsg(wnd);
  286.             break;
  287.         case BORDER:
  288.             return BorderMsg(wnd);
  289.         case LB_CHOOSE:
  290.             LBChooseMsg(wnd, p1);
  291.             return TRUE;
  292.         case KEYBOARD:
  293.             if (KeyboardMsg(wnd, p1, p2))
  294.                 return TRUE;
  295.             break;
  296.         case CLOSE_WINDOW:
  297.             return CloseWindowMsg(wnd);
  298.         default:
  299.             break;
  300.     }
  301.     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  302. }
  303.  
  304. /* --------- compute menu height -------- */
  305. int MenuHeight(struct PopDown *pd)
  306. {
  307.     int ht = 0;
  308.     while (pd[ht].SelectionTitle != NULL)
  309.         ht++;
  310.     return ht+2;
  311. }
  312.  
  313. /* --------- compute menu width -------- */
  314. int MenuWidth(struct PopDown *pd)
  315. {
  316.     int wd = 0, i;
  317.     int len = 0;
  318.  
  319.     wd = SelectionWidth(pd);
  320.     while (pd->SelectionTitle != NULL)    {
  321.         if (pd->Accelerator)    {
  322.             for (i = 0; keys[i].keylabel; i++)
  323.                 if (keys[i].keycode == pd->Accelerator)    {
  324.                     len = max(len, 2+strlen(keys[i].keylabel));
  325.                     break;
  326.                 }
  327.         }
  328.         if (pd->Attrib & CASCADED)
  329.             len = max(len, 2);
  330.         pd++;
  331.     }
  332.     return wd+5+len;
  333. }
  334.  
  335. /* ---- compute the maximum selection width in a menu ---- */
  336. static int SelectionWidth(struct PopDown *pd)
  337. {
  338.     int wd = 0;
  339.     while (pd->SelectionTitle != NULL)    {
  340.         int len = strlen(pd->SelectionTitle)-1;
  341.         wd = max(wd, len);
  342.         pd++;
  343.     }
  344.     return wd;
  345. }
  346.  
  347. /* ----- copy a menu command to a display buffer ---- */
  348. int CopyCommand(unsigned char *dest, unsigned char *src,
  349.                                         int skipcolor, int bg)
  350. {
  351.     unsigned char *d = dest;
  352.     while (*src && *src != '\n')    {
  353.         if (*src == SHORTCUTCHAR)    {
  354.             src++;
  355.             if (!skipcolor)    {
  356.                 *dest++ = CHANGECOLOR;
  357.                 *dest++ = cfg.clr[POPDOWNMENU]
  358.                             [HILITE_COLOR] [BG] | 0x80;
  359.                 *dest++ = bg | 0x80;
  360.                 *dest++ = *src++;
  361.                 *dest++ = RESETCOLOR;
  362.             }
  363.         }
  364.         else
  365.             *dest++ = *src++;
  366.     }
  367.     return (int) (dest - d);
  368. }
  369.  
  370.